using AdminApiTemplate.Common.Exceptions;
using AdminApiTemplate.Common.Helpers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using System.ComponentModel.DataAnnotations;

namespace AdminApiTemplate.Api.Controllers.BaseControllers
{
    /// <summary>
    /// 签名验证了即可访问的
    /// </summary>
    public class SignRequiredController : Controller
    {
        /// <summary>
        /// 密钥
        /// </summary>
        public static readonly Dictionary<string, string> Secrets = new Dictionary<string, string>
        {
        };

        /// <summary>
        /// 执行前
        /// </summary>
        /// <param name="context"></param>
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            var appId = context.HttpContext.Request.Headers["AppId"].FirstOrDefault();
            var sign = context.HttpContext.Request.Headers["Sign"].FirstOrDefault();
            var timeStamp = context.HttpContext.Request.Headers["TimeStamp"].FirstOrDefault();
            var signRequest = new SignRequest
            {
                AppId = appId,
                Sign = sign,
                TimeStamp = timeStamp
            };

            var invalids = ValidationHelper.Validate2(signRequest);
            if (!string.IsNullOrEmpty(invalids))
            {
                throw new WithCodeException((int)ErrorCodeEnum.InvalidArguments, invalids);
            }

            if (!Secrets.ContainsKey(appId))
            {
                throw new WithCodeException((int)ErrorCodeEnum.InvalidArguments, "AppId无效："+appId);
            }

            var time = ConvertHelper.GetDateTimeExact(timeStamp, "yyyyMMddHHmmss");
            if (!time.HasValue)
            {
                throw new WithCodeException((int)ErrorCodeEnum.InvalidArguments, "TimeStamp无效："+timeStamp);
            }

            var ts = DateTime.UtcNow - time.GetValueOrDefault();
            if (Math.Abs(ts.TotalSeconds) > 60)
            {
                throw new WithCodeException((int)ErrorCodeEnum.InvalidArguments, "请求已失效，请重新发起请求");
            }

            var body = "";
            if (context.HttpContext.Request.Body.CanRead)
            {
                context.HttpContext.Request.Body.Position= 0;
                var reader = new StreamReader(context.HttpContext.Request.Body);
                body = reader.ReadToEndAsync().Result;
                context.HttpContext.Request.Body.Position= 0;
            }

            var secret = Secrets[appId];
            var signInput = $"{body}{secret}{timeStamp}";
            var md5 = SecurityHelper.GetMD5String(signInput).ToUpper();
            if (md5!=sign.ToUpper())
            {
                throw new WithCodeException((int)ErrorCodeEnum.InvalidArguments, "Sign无效："+sign);
            }

            base.OnActionExecuting(context);
        }
    }

    /// <summary>
    /// 签名请求
    /// </summary>
    public class SignRequest
    {
        /// <summary>
        /// AppId
        /// </summary>
        [Required(ErrorMessage = "必填")]
        [RegularExpression("^[0-9a-z]{16}$", ErrorMessage = "无效")]
        public string AppId { get; set; }

        /// <summary>
        /// 时间
        /// </summary>
        [Required(ErrorMessage = "必填")]
        [RegularExpression("^[0-9]{14}$", ErrorMessage = "无效")]
        public string TimeStamp { get; set; }

        /// <summary>
        /// 签名
        /// </summary>
        [Required(ErrorMessage = "必填")]
        public string Sign { get; set; }
    }
}
